package archsw0904.controller.catalog;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import archsw0904.controller.authentication.AuthenticationManagerLocal;
import archsw0904.controller.catalog.SearchOrder;
import archsw0904.model.Book;

/**
 * Session Bean implementation class Calculator
 */
@Stateless
@WebService
public class Catalog implements CatalogRemote, CatalogLocal {
	
	@PersistenceContext
    private EntityManager em;
	@EJB
	private AuthenticationManagerLocal am;

	@WebMethod
	public Book createBook(String isbn, String author, String title,
			String category, String tag, BigDecimal price, String editor, Integer availableCopies , String year,  boolean shopWindow, int token) {
		
		if (am.getRoleByToken(token).compareTo("admin") != 0)
			return null;
		
		Query q = em.createNamedQuery("Book.findBookIsbn").setParameter("isbn", isbn);		
		try {
			q.getSingleResult();
			System.out.print("libro gia' presente");
			return null;
		} catch (NoResultException e) {
		
		Book b = new Book();
		b.setTitle(title);
		b.setAuthor(author);
		b.setCategory(category);
		b.setEditor(editor);
		b.setIsbn(isbn);
		b.setPrice(price);
		b.setTag(tag);
		b.setAvailableCopies(availableCopies);
		b.setCopiesInStockroom(availableCopies);
		b.setShopWindow(shopWindow);
		b.setYear(year);
		em.persist(b);
		
		return b;
		}
	}

	@SuppressWarnings("unchecked")
	@WebMethod
	public List<Book> queryBook(QueryParam fields) throws  archsw0904.controller.catalog.NullMandatoryFieldException{
		StringBuffer queryString = new StringBuffer("SELECT OBJECT(obj) FROM Book obj");
		StringBuffer queryWhere = new StringBuffer("");
		Query q = null;
		List<String> partialWhere = new LinkedList<String>();
		Boolean isFirst = true;
		HashMap<QueryableFieldOrdered, String> realFields = fields.getFields();
		
		
		for ( QueryableFieldOrdered field : realFields.keySet())  {
			
			if (field.getQueryField() == QueryableField.Price){
				Pattern p = Pattern.compile("[0-9]+[.]*[0-9]*");
				Matcher m;
				boolean matchFound ;
				if (realFields.get(field)!=null){
					System.out.print("prezzo dentro catalog" + realFields.get(field));
					m = p.matcher(realFields.get(field));
					matchFound = m.matches();
					if (!matchFound)
						throw new archsw0904.controller.catalog.NullMandatoryFieldException("price format not correct "+ realFields.get(field)) ;	
				}
			}
			if(realFields.get(field)!=null){
				partialWhere.add(field.getQueryField().formatParam("obj", realFields.get(field)));
			}
			
		}
		
		for (String p : partialWhere) {
			if (!isFirst) {
				queryWhere.append(" and ");		
			}
			queryWhere.append(p);
			isFirst = false;
		}
		
		if ( queryWhere.toString().compareTo("") != 0 ) {
			queryString.append(" WHERE ").append(queryWhere);
		}
		
		//sezione ordinamento risultati
		boolean empty = true;
		for ( QueryableFieldOrdered field : realFields.keySet())  {
			System.out.print("dentro il ciclo dell'ordinamento");
			if (field.getOrder()!= SearchOrder.Default){
				if (empty){
					queryString.append(" ORDER BY ");
					empty=false;
				}
				queryString.append(" obj.");
				queryString.append(field.getQueryField().toString());
				queryString.append(" ");
				queryString.append(field.getOrder().toString());
			}
			
			System.out.print(field.getOrder().toString());
		}
		
		System.out.println("#########" + queryString);
		q = em.createQuery(queryString.toString());
		List<Book> result  = q.getResultList();
		return result == null ? new LinkedList<Book>() : result;
	}

	@SuppressWarnings("unchecked")
	@WebMethod
	public List<Book> queryPromotions() {
		return em.createNamedQuery("Book.shopWindowBook").getResultList();
	}
}
